require "Common/define"
require "Logic/Config"

UILoading = {};
HelperFunc.SetUIEnv(UILoading)
local this = UILoading

this.sli_pro = nil;
this.loadTip = nil;

this.LoadStep_Start = 1    -- 加载 开始
this.LoadStep_Lua = 2      -- 加载 Lua相关 比如本地配置
this.LoadStep_WaitMsg = 3  -- 加载 等待消息
this.LoadStep_Model = 4    -- 加载 模型
this.LoadStep_UI = 5       -- 加载 UI
this.LoadStep_End = 6      -- 加载 完成
this.LoadStep_Process = { 5, 15, 15, 0, 40, 25 } --第四阶段，暂时不需要加载模型，所以为0

function UILoading.Init(account)
    this.account = account
    local name, package = getUIName(PanelResNames.UILoading);
    panelMgr:ShowUI(name, package, this.OnCreate, Config.useLocalUI);
    panelMgr.pauseChangeSound = true;
end

function UILoading.OnCreate(obj)
    destroyAllUIIgnore(function(name)
        return IsNoDelete(name) or
                getUIName(name) == getUIName(PanelResNames.UILoading)
    end)

    sli_pro = obj:GetChild("Slider");
    loadTip = obj:GetChild("LoadingTips");
    local ctrlPA = obj:GetController("PA")
    if ctrlPA then
        if AppConst.drawingState == 0 then
            ctrlPA.selectedIndex = 0
        else
            ctrlPA.selectedIndex = 1
        end
    end
    sli_pro.value = 100 - 0 -- 反向遮罩
    this.UpdateProcess(0)
    local state = LoadStep_StateStart.New(LoadStep_Start, this.UpdateProcess)
    state:Enter()
end

function UILoading.OnDestroy()
    sli_pro = nil
    loadTip = nil

    --HelperFunc.UnloadUnusedAssets()
end

function UILoading.UpdateProcess(value)
    local value = value * 100 + 100 - sli_pro.value
    if value > 100 then
        value = 100
    end
    sli_pro.value = 100 - value -- 反向遮罩
    loadTip.text = "更新进度：" .. math.ceil(value) .. "%"
end

LoadStep_StateBase = Class("LoadStep_StateBase")
local _M = LoadStep_StateBase
function _M:ctor(LoadStep, updateProcessFunc)
    self.processRadio = LoadStep_Process[LoadStep] / 100      -- 加载比例
    self.updateProcessFunc = updateProcessFunc              -- 进度条

    self.loading = false
    self.loadedCount = 0
    self.loadTotalCount = 1
end
function _M:dtor()

end
function _M:Enter()
    self:DelTimer()
    self.timer = utimer.frameCall(function()
        self:Update()
    end, -1)
end
function _M:Leave()
    self:DelTimer()
end
function _M:Update()
    if self.loading then
        return
    end
    if self.loadedCount >= self.loadTotalCount then
        self:LoadAllFinish()
        self:Leave()
        return
    end
    self.loading = true
    self:LoadRes(function(loadCount)
        local loadCount = loadCount or 1
        self.loading = false
        self.loadedCount = self.loadedCount + loadCount
        self.updateProcessFunc(loadCount / self.loadTotalCount * self.processRadio)
    end)
end
function _M:LoadRes(call)
    -- 子类实现
end
function _M:LoadAllFinish()
    -- 子类实现
end
function _M:DelTimer()
    if self.timer then
        utimer.remove(self.timer)
        self.timer = nil
    end
end

-------------------------- 加载开始 --------------------------
LoadStep_StateStart = Class("LoadStep_StateStart", LoadStep_StateBase)
local _M = LoadStep_StateStart
function _M:LoadRes(call)
    call()
end
function _M:LoadAllFinish()
    -- 进入加载Lua阶段 TODO 目前暂时不使用lua流程 放在最前面做
    local state = LoadStep_StateLua.New(LoadStep_Lua, self.updateProcessFunc)
    state:Enter()
end

-------------------------- 加载Lua --------------------------
_G.LoadStep_StateLua = Class("LoadStep_StateLua", LoadStep_StateBase)
local _M = LoadStep_StateLua
function _M:ctor(processRadio, updateProcessFunc)
    LoadStep_StateBase.ctor(_M, processRadio, updateProcessFunc)
end
function _M:LoadRes(call)
    call()
    --[[for i = 1, 5 do
        local name = self.LoadLuaTable[self.loadedCount + 1]
        if name == nil then 
            break
        end
        local t = G.dataTable[name]
        call()
    end--]]
end
function _M:LoadAllFinish()
    -- 1 初始化控制器
    self.LoadInitCtrl()

    -- 2 进入等待服务器阶段
    local state = LoadStep_StateWaitMsg.New(LoadStep_WaitMsg, self.updateProcessFunc)
    state:Enter()
end

function _M.InitLuaTable()
    for index, value in ipairs(_M.LoadLuaTable) do
        local t = G.dataTable[value]
    end
end

-------------------------- 等待服务器 --------------------------
LoadStep_StateWaitMsg = Class("LoadStep_StateWaitMsg", LoadStep_StateBase)
local _M = LoadStep_StateWaitMsg
function _M:ctor(processRadio, updateProcessFunc)
    LoadStep_StateBase.ctor(_M, processRadio, updateProcessFunc)
    self.finishCall = nil
    ListenEvent(Config.EventType.Fresh_BattleFormation, self.MsgBattleFormation, self)
end
function _M:LoadRes(call)
    self.loading = false
    if HelperFunc.GetSyncAttrAllFinish() then
        self.loading = true
        -- 发送阵容请求
        self.finishCall = call
        dungeonHandler.sendFormation()
    end
end
function _M:LoadAllFinish()
    CloseEvent(Config.EventType.Fresh_BattleFormation, self.MsgBattleFormation, self)

    -- 进入加载模型阶段
    local state = LoadStep_StateModel.New(LoadStep_Model, self.updateProcessFunc)
    state:Enter()
end
function _M:MsgBattleFormation()
    if self.finishCall then
        self.finishCall()
    end
end
-------------------------- 加载模型 --------------------------
LoadStep_StateModel = Class("LoadStep_StateModel", LoadStep_StateBase)
local _M = LoadStep_StateModel
function _M:ctor(processRadio, updateProcessFunc)
    LoadStep_StateBase.ctor(_M, processRadio, updateProcessFunc)
    self.modelList = UILoading.GetLoadModelResList()
    self.loadTotalCount = #self.modelList

    self.onceLoadCount = 4  -- 一次性加载
end
function _M:LoadRes(call)
    local maxIndex = self.loadedCount + self.onceLoadCount
    local maxCount = #self.modelList
    if maxIndex > maxCount then
        maxIndex = maxCount
    end
    local loadedCount = 0
    local loadMaxCount = maxIndex - self.loadedCount
    for i = self.loadedCount + 1, maxIndex do
        local res = self.modelList[i]
        loadResource(res, function(prefabobj)
            local array = string.split(res, "#");
            if #array > 1 then
                local type = array[2];
                if type == "Effect" then
                    local obj_name = nil
                    local ret = string.match(array[1], "/[^/]*[^/]$")
                    if ret ~= nil then
                        obj_name = string.gsub(ret, "/", "")
                    end
                    SpineEffectManager.createEffectPool(panelMgr.BattleMain.transform, prefabobj, 1, obj_name);
                elseif type == "Model" then
                    --BattleSceneCacheResouce:AddReUseObj(res,newObject(prefabobj))
                elseif type == "Map" then
                    local mapInstanse = newObject(prefabobj);
                    mapInstanse.transform:SetParent(panelMgr.BattleMain.transform);
                    BattleSceneCacheResouce:SaveMapInstance(mapInstanse)
                elseif type == "FlyText" then
                    objectPoolMgr:CreatePool(prefabobj.name, 2, 5, prefabobj);
                end
            end
            loadedCount = loadedCount + 1
            if loadedCount >= loadMaxCount then
                call(loadedCount)
            end
        end);
    end
end
function _M:LoadAllFinish()
    -- 进入加载UI阶段
    logicMgr.GuideMgr.OnCreate()
    local state = LoadStep_StateUI.New(LoadStep_UI, self.updateProcessFunc)
    state:Enter()
end
function UILoading.GetLoadModelResList()
    local mapId = tostring(logicMgr.MapManager.getMapId());
    local mapName = logicMgr.MapManager.getBattleMapName();

    local resList = {};

    if mapName == nil then
        mapName = 'AutoFightMap8';
    end
    --if FightManager.fightType == EnumConst.FightTypeConst.DUNGEON then
        --table.insert(resList, "Prefabs/MapPref/" .. mapName .. "#Map");
    --end

    local tab_role = {};
    local formation = logicMgr.FormationManager.GetFormation(EnumConst.FormationType.Duplicate, true);
    if formation ~= nil then
        for k,v in pairs(formation) do
            --if k ~= 6 then
                local partnerId = tostring(v);
                if toNumber(partnerId) > 0 then
                    local heroData = logicMgr.HeroManager.getHeroDatabyPartnerId(partnerId)
                    if heroData then
                        table.insert(tab_role,heroData.partnerModelId)
                    end
                end
            --end
        end
    end

    for i=1,#tab_role do
        local heroCfg = G.dataTable["t_hero"][tostring(tab_role[i])];
        if heroCfg ~= nil then
            local modefile = heroCfg.f_HeroModel;
            local path = logicMgr.HeroManager.GetHeroDrawingRolePath(tab_role[i]);
            if modefile ~= nil and modefile ~= "" and indexofTable(resList,path.."#Model") < 1 then
                table.insert(resList,path.."#Model");
            end
        end
    end

    if not BattleScene.isShow then
        return resList
    end

    -- 敌人
    --[[local tab_role = {};
    local battleMapCfg = G.dataTable["t_battlemap"][mapId];
    if battleMapCfg ~= nil then
        for i = 1, 3 do
            local monsterIds = decodeJsonStrToTabel(battleMapCfg["f_MonsterId"..i]);
            for i=1,#monsterIds do
                if indexofTable(tab_role,monsterIds[i]) <= 0 then
                    table.insert(tab_role,monsterIds[i]);
                end
            end
        end
    else
        logError("找不到地图数据t_battlemap ，id:  "..mapId)
    end

    -- 自己
    local formation = logicMgr.FormationManager.GetFormation(EnumConst.FormationType.Duplicate, true);
    if formation ~= nil then
        for k,v in pairs(formation) do
            --if k ~= 6 then
                local partnerId = tostring(v);
                if toNumber(partnerId) > 0 then
                    local heroData = logicMgr.HeroManager.getHeroDatabyPartnerId(partnerId)
                    if heroData then
                        table.insert(tab_role,heroData.partnerModelId)
                    end
                end
            --end
        end
    end

    local tab_skill = {};
    for i=1,#tab_role do
        local heroCfg = G.dataTable["t_hero"][tostring(tab_role[i])];
        if heroCfg ~= nil then
            local modefile = heroCfg.f_HeroModel;
            local roleCfg = G.dataTable["t_roleconfig"][tostring(modefile)];
            if roleCfg ~= nil then
                local skills = roleCfg["nomalSkill"] --decodeJsonStrToTabel(roleCfg["nomalSkill"]);
                for i=1,#skills do
                    if indexofTable(tab_skill,skills[i]) <= 0 then
                        table.insert(tab_skill,skills[i]);
                    end
                end
            end
        end
    end

    for i=1,#tab_role do
        local heroCfg = G.dataTable["t_hero"][tostring(tab_role[i])];
        if heroCfg ~= nil then
            local modefile = heroCfg.f_HeroModel;
            local path = logicMgr.HeroManager.GetHeroDrawingRolePath(tab_role[i]);
            if modefile ~= nil and modefile ~= "" and indexofTable(resList,path.."#Model") < 1 then
                table.insert(resList,path.."#Model");
            end
        end
    end
    for i=1,#tab_skill do
        local skillShow = G.dataTable["t_skillshow"][tostring(tab_skill[i])];
        if skillShow ~= nil then

            --local preeffect = skillShow.f_SkillFResource;
            --if preeffect ~= nil and preeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..preeffect.."#Effect") < 1 then
            --	table.insert(resList,"Prefabs/Skill/"..preeffect.."#Effect");
            --end

            local preeffectList = skillShow.f_SkillFResource;
            --local preeffectList = string.split(preeffectRaw,",");
            local preeffect = preeffectList[1];
            if preeffect ~= nil and preeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..preeffect.."#Effect") < 1 then
                table.insert(resList,"Prefabs/Skill/"..preeffect.."#Effect");
            end

            if #preeffectList > 1 then
                preeffect = preeffectList[2];
                if preeffect ~= nil and preeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..preeffect.."#Effect") < 1 then
                    table.insert(resList,"Prefabs/Skill/"..preeffect.."#Effect");
                end
            end

            local flyeffect = skillShow.f_FlyFResource;
            if flyeffect ~= nil and flyeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..flyeffect.."#Effect") < 1 then
                table.insert(resList,"Prefabs/Skill/"..flyeffect.."#Effect");
            end
            local hiteffect = skillShow.f_HitFResource;
            if hiteffect ~= nil and hiteffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..hiteffect.."#Effect") < 1 then
                table.insert(resList,"Prefabs/Skill/"..hiteffect.."#Effect");
            end
            local preendeffect = skillShow.f_SkillBResource;
            if preendeffect ~= nil and preendeffect ~= "" and indexofTable(resList,"Prefabs/Skill/"..preendeffect.."#Effect") < 1 then
                table.insert(resList,"Prefabs/Skill/"..preendeffect.."#Effect");
            end
        end
    end]]

    return resList
end

-------------------------- 加载UI --------------------------
LoadStep_StateUI = Class("LoadStep_StateUI", LoadStep_StateBase)
local _M = LoadStep_StateUI
function _M:ctor(processRadio, updateProcessFunc)
    LoadStep_StateBase.ctor(_M, processRadio, updateProcessFunc)
    self.uiList, self.showList = self:GetUIResList()
    self.loadTotalCount = #self.uiList

    self.onceLoadCount = 1  -- 一次性加载
end
function _M:LoadRes(call)
    local maxIndex = self.loadedCount + self.onceLoadCount
    local maxCount = #self.uiList
    if maxIndex > maxCount then
        maxIndex = maxCount
    end
    local loadedCount = 0
    local loadMaxCount = maxIndex - self.loadedCount
    for i = self.loadedCount + 1, maxIndex do
        local res = self.uiList[i]
        local name, packageName = getUIName(res)
        if panelMgr:GetUI(name) then
            loadedCount = loadedCount + 1
            if loadedCount >= loadMaxCount then
                call(loadedCount)
            end
        else
            print("========", name, packageName)
            panelMgr:CreatePanel(name, packageName, function(ui)
                ui.visible = false
                loadedCount = loadedCount + 1
                if loadedCount >= loadMaxCount then
                    call(loadedCount)
                end
            end, nil, nil, false)
        end

    end
end
function _M:LoadAllFinish()
    for index, value in ipairs(self.showList) do
        local name, package = getUIName(value);
        local ctrl = CtrlManager.GetCtrl(value)
        panelMgr:ShowUI(name, package, ctrl.OnCreate, Config.useLocalUI);
    end

    -- 进入加载完成阶段
    local state = LoadStep_StateEnd.New(LoadStep_End, self.updateProcessFunc)
    state:Enter()
end
function _M:GetUIResList()
    -- 加载列表
    local resList = {}
    table.insert(resList, PanelResNames.BackGround)
    table.insert(resList, PanelResNames.UIHeadMenu)
    table.insert(resList, PanelNames.UIBottom)
    --table.insert(resList,PanelNames.UIDebug)
    table.insert(resList, PanelNames.UIBloodBar)
    table.insert(resList, PanelNames.Headbar)
    table.insert(resList, PanelNames.UIRedDots)
    table.insert(resList, PanelNames.UIBattle)
    if logicMgr.FuncOpenManager.isOpen(Config.FuncOpenType.City, false) then
        table.insert(resList, PanelResNames.UICity)
    end

    -- table.insert(resList,PanelNames.UIDrawAnimation)//优化 不进行预先加载add by dzc

    -- 显示列表
    local showList = {}
    --table.insert(showList,PanelNames.UIDebug)
    table.insert(showList, PanelNames.UIBloodBar)
    return resList, showList
end

-------------------------- 加载完成 --------------------------
LoadStep_StateEnd = Class("LoadStep_StateUI", LoadStep_StateBase)
local _M = LoadStep_StateEnd
function _M:LoadRes(call)
    call()
end
function _M:LoadAllFinish()
    if logicMgr.LoginManager.GetLoginType() == EnumConst.LoginState.Create then
        showUI(PanelNames.Page_VoiceChangeLanguage, function()
            self:playVideo()
        end)
    else
        utimer.delayCall(function()
            self:FinishFunction()
        end, 500)
    end
end

function _M:playVideo()

    --showUI(PanelNames.UIPlayVideo, AudioManager.VideoInfo[1], true, function()
    --    self:FinishFunction()
    --end, AudioManager.VideoInfo[2])

    --跳过CG，直接进表演战斗
    local id = dataTable.getDataTableByStringId("t_global",179,"f_int_value")
    if id > 0 then
        logicMgr.GuideMgr.Resume()
        logicMgr.BattlePlaybackManager.playReport(101,EnumConst.FightTypeConst.PerformBattle)
        logicMgr.StoryMgr.callback = function()
            self:FinishFunction()
        end

    else
        logicMgr.GuideMgr.Resume()
        self:FinishFunction()
    end

end

function _M:FinishFunction()
    panelMgr.pauseChangeSound = false;
    hideOtherUI(true);
    --showUI(PanelNames.UIHeadMenu,true);
    showUI(PanelNames.UIBottom);
    DestoryUI(PanelResNames.UILoading)
    logicMgr.GuideMgr.CheckGuide(true)

    --logicMgr.ActiveManager.startActivePopUpTips();
    logicMgr.PasteFaceNoticeManager.startPasteFaceNotice();

    WWISE.WwiseBehavior.UnloadBank("Login_Bank")
    collectgarbage("collect")
    logicMgr.GuildBattlePlusManager.setEntranceRed(EnumConst.GuildBattlePlusType.Territory, "false")
    logicMgr.GuildBattlePlusManager.setEntranceRed(EnumConst.GuildBattlePlusType.Championship, "false")
    logicMgr.LBSManager.StartLocation();
    -- iOS Widget: 数据初始化
    if CompareOriginVersion("1.4.2.0001") then
        local heroMgr, mapMgr, towerMgr = logicMgr.HeroManager, logicMgr.MapManager, logicMgr.TowerManager
        local nick        = heroMgr.GetRoleName()
        local tick        = heroMgr.getSettleTime()
        local maxHangTime = heroMgr.getSettleingMaxTime()
        local power       = heroMgr.GetHerosSumPower()
        local stage       = mapMgr.getMapId()
        local towerInfo   = towerMgr.returnTowerInfo(1) or {}
        local tower       = towerInfo.layerId or 0
        local heroList    = heroMgr.getOwnerHeroListReadOnly()
        local heros       = #heroList    
        LoginSDK.GetInstance():InitWidgetData(nick, tick, maxHangTime, power, stage, tower, heros)
    end
end

function LoadStep_StateLua.LoadInitCtrl()
    luaMgr:InitLuaData()


    require "View/UILevel/UILevelRecode"
    require "View/CommonUI/UICommonPop"
    require("View/" .. PanelNames.UIRedDots)
    require("View/" .. PanelNames.UISysTips)

    dataTable.getDataTable("t_monsterteam")--提前载表
    dataTable.getDataTable("t_item")
    collectgarbage("count")
    -- TODO 动态加载Manager 
    -- 使用接口 logicMgr.xxx会自动加载 并且第一次加载时会调用xxx.Init()接口
end

LoadStep_StateLua.LoadLuaTable = {
    -- TODO 动态加载table 
    -- 使用时_G.dataTable["xxx"]会自动加载
}

return UILoading;